const Joi = require("joi");
const moment = require("moment");
const AppleAuthUtil = require("../utils/apple");
module.exports = class UserController extends colpu.Controller {
  /**
   * @api {post} /user/login 用户登录
   * @apiDescription 用户登录
   * @apiGroup 用户接口
   * @apiVersion 1.0.0
   *
   * @apiSuccess {Number} status 状态码
   * @apiSuccess {String} message 消息
   * @apiSuccess {Object} data 返回结果
   * @apiSuccessExample {json} Success-Response:
   * HTTP/1.1 200 OK
   *  {
   *    "data": true,
   *    "status": 0,
   *    "message": "ok"
   *  }
   */
  async login(ctx) {
    // 参数验证
    await ctx.validateAsync({
      body: {
        username: Joi.string().allow(null, ""),
        phone: Joi.string().allow(null, ""),
        email: Joi.string().allow(null, ""),
        password: Joi.string().required(),
      },
      status: 10001,
    });
    const body = ctx.request.body;
    try {
      const userInfo = await this.service.user.findOne(this._clearEmpty(body));
      if (userInfo) {
        this._setContextUserInfo(ctx, userInfo);
        ctx.respondEncrypt(userInfo);
      } else {
        ctx.respond(null, -1, "用户名或密码错误～");
      }
    } catch (error) {
      ctx.throw(error.message, -1, "查询出错了～");
    }
  }
  _clearEmpty(data) {
    Object.keys(data).forEach((key) => {
      if (!data[key]) {
        delete data[key];
      }
    });
    return data;
  }

  async register(ctx) {
    // 参数验证
    await ctx.validateAsync({
      body: {
        username: Joi.string().required(),
        password: Joi.string().required(),
        email: Joi.string(),
        phone: Joi.string().allow(null, ""),
        nickname: Joi.string().allow(null, ""),
        avatar: Joi.string().allow(null, ""),
        year: Joi.string().allow(null, ""),
        gender: Joi.string().allow(null, ""),
        country: Joi.string().allow(null, ""),
        province: Joi.string().allow(null, ""),
        city: Joi.string().allow(null, ""),
      },
      status: 10001,
    });
    const body = ctx.request.body;
    if (!body.nickname) {
      body.nickname = body.username;
    }
    let userInfo;
    try {
      userInfo = await this.service.user.register(this._clearEmpty(body));
    } catch (error) {
      console.error(error.message);
    }
    if (userInfo) {
      this._setContextUserInfo(ctx, userInfo);
      ctx.respondEncrypt(userInfo);
    } else {
      ctx.throw(-1, "注册失败了");
    }
  }

  /**
   * @api {put} /api/user 更新用户
   * @apiDescription 更新用户
   * @apiGroup 用户接口
   * @apiVersion 1.0.0
   *
   * @apiParam {Number|Null} [type] 用户类型：1、漫画，2、乐谱
   * @apiParam {Number} [id] 用户id
   * @apiParam {String} [username] 用户名称
   * @apiParam {String} [nickname] 用户名字昵称
   * @apiParam {String} [password] 密码
   * @apiParam {Number} [phone] 电话号码
   * @apiParam {String} [email] 邮箱
   * @apiParam {Number} [level] 用户等级，与用户类型配合，数值越高权限越低
   * @apiParam {Number} [status] 用户状态，0表示禁用，1表示启用
   * @apiParam {Number} [role_id] 用户角色id
   *
   * @apiSuccess {Number} status 状态码
   * @apiSuccess {String} message 消息
   * @apiSuccess {Object} data 返回结果
   * @apiSuccessExample {json} Success-Response:
   * HTTP/1.1 200 OK
      {
        "data": {
          "id": 0
        },
        "status": 0,
        "message": "ok"
      }
  */
  async update(ctx) {
    // 参数验证
    await ctx.validateAsync({
      body: {
        uid: Joi.string().required(),
      },
      status: 10001,
    });
    const res = await this.service.user.update(ctx.request.body);
    if (res === 1) {
      ctx.respond(null, 0, "更新成功");
    } else {
      ctx.respond(null, -1, "没有任何更新");
    }
  }

  async check(ctx) {
    // 参数验证
    await ctx.validateAsync({
      body: {
        username: Joi.string(),
        email: Joi.string(),
        phone: Joi.string(),
      },
      status: 10001,
    });
    let result = await this.service.user.check(ctx.request.body);
    ctx.respond({ status: !result });
  }

  async appleAuth(ctx) {
    await new AppleAuthUtil(ctx).auth(ctx);
  }
  async appleAuthCallback(ctx) {
    await new AppleAuthUtil(ctx).authCallback(ctx);
  }

  /**
   * @api {put} /api/user/thirdauth 用户三方授权
   * @apiDescription 用户三方授权
   * @apiGroup  用户接口
   * @apiVersion 1.0.0
   *
   * @apiSuccess {Number} status 状态码
   * @apiSuccess {String} message 消息
   * @apiSuccess {Object} data 返回结果
   * @apiSuccess {Boolen} isDecrypt 是否需要解密
   * @apiSuccessExample {json} Success-Response:
   * HTTP/1.1 200 OK
      {
        "data": {
          ...
        },
        "status": 0,
        "message": "ok"
      }
  */
  async thirdAuth(ctx) {
    await ctx.validateAsync({
      body: {
        type: Joi.number().required(),
        openid: Joi.string().required(),
      },
      status: 10001,
    });
    const body = ctx.request.body;
    const putData = {
      type: body.type,
      openid: body.openid,
      unionid: body.unionid,
      username: body.username,
      nickname: body.nickname || "元气少年",
      sex: body.sex,
      gender: body.gender,
      avatar: body.avatar || body.profile_image_url,
      city: body.city,
      province: body.province,
      country: body.country,
    };
    // const putData = {
    //   openid: 'FC5BD3E76D431C7697290170B0C76C20',
    //   unionid: 'UID_54276B13B067D7144FF6B42E6CE08136',
    //   username: '狼鹰',
    //   nickname: '狼鹰',
    //   gender: '男',
    //   avatar: 'http://thirdqq.qlogo.cn/g?b=oidb&k=3WhOd5mPSYBC4uUjc9qFSw&kti=ZDZz1AAAAAA&s=100&t=1556726785',
    //   city: '深圳',
    //   province: '广东',
    //   country: undefined
    // }
    const userInfo = await this.service.user.thirdAuth(putData);
    if (userInfo) {
      this._setContextUserInfo(ctx, userInfo);
      ctx.respondEncrypt(userInfo);
    } else {
      ctx.throw(-1, "查询出错了～");
    }
  }

  async thirdAuthBind(ctx) {
    await ctx.validateAsync({
      body: {
        type: Joi.number().required(),
        uid: Joi.string().required(),
        openid: Joi.string().required(),
      },
      status: 10001,
    });
    const body = ctx.request.body;
    const putData = {
      type: body.type,
      uid: body.uid,
      openid: body.openid,
      unionid: body.unionid,
    };
    let status = 0;
    try {
      status = await this.service.user.thirdAuthBind(putData);
    } catch (error) {
      ctx.throw(-1, "绑定失败");
    }
    console.log(status, 999999);
    ctx.respond(
      null,
      status,
      status === 0 ? "绑定成功" : "该账号已被绑定到其它账号，请换其它试试。"
    );
  }
  // 解绑三方账号
  async thirdUnbind(ctx) {
    await ctx.validateAsync({
      body: {
        openid: Joi.string().required(),
      },
      status: 10001,
    });
    const { openid } = ctx.request.body;
    try {
      let status = await this.service.user.updateThirdbindStatus({ openid }, 0);
      ctx.respond(null, 0, status == 0 ? "已被解绑了" : "解绑成功");
    } catch (error) {
      ctx.throw(-1, "解绑失败，稍后再试");
    }
  }

  /**
   * @api {get} /api/user 获取用户
   * @apiDescription 获取用户
   * @apiGroup 用户接口
   * @apiVersion 1.0.0
   *
   * @apiHeader {String} Authorization 用户token
   * @apiHeaderExample {json} Header-Example:
   * {
   *  "Authorization": "Bear ud9lC7iiYUC9LWytfd0KY8Qf7ixu4SFl96TJhlpdBFSrFBBNnqEQaha5BtdOGvHSpIVGoDJmklxXDVjSOgCPH8tkDCtS4+C/3s6uNpJpnb8="
   * }
   *
   * @apiParam {String} [openid] 用户openid
   *
   * @apiSuccess {Number} status 状态码
   * @apiSuccess {String} message 消息
   * @apiSuccess {Object} data 返回结果
   * @apiSuccessExample {json} Success-Response:
   * {
   *   "data": {
   *     "id": 1, // @required 用户id自增
   *     "uid": "906ba9af147d88cdf8c544795eaf0a64", // @required 用户id自增
   *     "username": "test", // 用户名称
   *     "nickname": "", // 用户名字昵称
   *     "phone": "", // 电话号码
   *     "email": "", // 邮箱
   *     "status": 1, // 用户状态，0表示禁用，1表示启用
   *     "role_id": 0, // 用户角色id
   *     "token": "ud9lC7iiYUC9LWytfd0KY8Qf7ixu4SFl96TJhlpdBFSrFBBNnqEQaha5BtdOGvHSpIVGoDJmklxXDVjSOgCPH8tkDCtS4+C/3s6uNpJpnb8=",
   *     "openid": "906ba9af147d88cdf8c544795eaf0a64" // 三方授权的openid
   *   },
   *   "status": 0,
   *   "message": "ok"
   * }
   */
  async getUserInfo(ctx) {
    await ctx.validateAsync({
      query: {
        uid: Joi.string().required(),
      },
      status: 10001,
    });
    let userInfo = ctx.session.user;
    if (!userInfo) {
      const uid = ctx.query.uid;
      try {
        userInfo = await this.service.user.findOne({ uid });
      } catch (error) {
        ctx.throw(500, error.message);
      }

      this._setContextUserInfo(ctx, userInfo);
    }
    // 阅览器缓存60秒
    ctx.cacheControl = { maxAge: 60 };
    ctx.respondEncrypt(userInfo);
  }

  /**
   * @api {post} /user/logout 用户登出
   * @apiDescription 用户登出
   * @apiGroup 用户接口
   * @apiVersion 1.0.0
   *
   * @apiSuccess {Number} status 状态码
   * @apiSuccess {String} message 消息
   * @apiSuccess {Object} data 返回结果
   * @apiSuccessExample {json} Success-Response:
   * HTTP/1.1 200 OK
   *  {
   *    "data": true,
   *    "status": 0,
   *    "message": "ok"
   *  }
   */
  logout(ctx) {
    ctx.session.user = null;
    ctx.cookies.set("user", null, { signed: true, maxAge: 0 });
    ctx.respond(true, 0, "登出成功");
  }

  /**
   * 设置登录cookie及session信息
   * @param ctx {object} 请求上下文
   * @param userInfo {object} 用户信息
   * @return undefined
   */
  _setContextUserInfo(ctx, userInfo) {
    ctx.session.user = userInfo;
    ctx.cookies.set("user", userInfo.uid, {
      httpOnly: false,
      signed: true,
      maxAge: this.config.session.maxAge,
    });
  }

  /**
   * @api {get} /api/user/userset 获得用户设置
   * @apiDescription 用户设置
   * @apiGroup  全局配置接口
   * @apiVersion 1.0.0
   *
   * @apiSuccess {Number} status 状态码
   * @apiSuccess {String} message 消息
   * @apiSuccess {Object} data 返回结果
   * @apiSuccessExample {json} Success-Response:
   * HTTP/1.1 200 OK
      {
        "data": {
          ...
        },
        "status": 0,
        "message": "ok"
      }
  */
  async getUserSet(ctx) {
    await ctx.validateAsync({
      query: {
        uid: Joi.string().required(),
      },
      status: 10001,
    });
    // 强制阅览器不缓存
    ctx.cacheControl = { noCache: true };
    const res = await this.service.user.getUserSet(ctx.query);
    ctx.respond(res);
  }
  /**
   * @api {put} /api/user/userset 提交用户设置
   * @apiDescription 提交用户设置
   * @apiGroup  全局配置接口
   * @apiVersion 1.0.0
   *
   * @apiSuccess {Number} status 状态码
   * @apiSuccess {String} message 消息
   * @apiSuccess {Object} data 返回结果
   * @apiSuccessExample {json} Success-Response:
   * HTTP/1.1 200 OK
      {
        "status": 0,
        "message": "ok"
      }
  */
  async putUserSet(ctx) {
    const { version } = ctx.query;
    let schema = {
      type: Joi.string().required(),
      value: Joi.string().required(),
      uid: Joi.string().required(),
    };
    let body = ctx.request.body;
    if (version <= "1.0.4") {
      schema = {
        save_key: Joi.string().required(),
        save_value: Joi.string().required(),
        user_id: Joi.string().required(),
      };
      body = {
        type: body.save_key,
        value: body.save_value,
        uid: body.user_id,
      };
    }
    await ctx.validateAsync({
      body: schema,
      status: 10001,
    });
    await this.service.user.putUserSet(body);
    ctx.respond(null);
  }

  async userVipInfo(ctx) {
    await ctx.validateAsync({
      query: {
        uid: Joi.string().required(),
      },
      status: 10001,
    });
    const { uid } = ctx.query;
    // 获取到用户充值权益未失效的数据
    const record = await this.service.pay.getPayRecord(uid);
    // 没获取到用户的充值记录则，返回
    if (!record.length) {
      return ctx.respond(null);
    }

    const payTypes = await this.service.productPayType.payType({
      mode: "object",
    });
    // 获得VIP最早开始时间
    let updateVipExpire;
    const payProductIdSets = new Set();
    record.forEach((item, i) => {
      // 由于健值是字符串，所以这里需要转换一下
      const key = item.pay_type.toString();
      if (Object.keys(payTypes).indexOf(key) == -1) {
        return;
      }
      const currentType = payTypes[key];
      // 支付产品id
      if (currentType.id === 10) {
        payProductIdSets.add(item.pro_id);

        // 只有VIP才做过期时间操作
      } else if (currentType.id === 11 || currentType.fid === 11) {
        // 以毫秒为单位的时间间隔
        const timeStep = moment(item.end_time) - moment(item.start_time);
        // 将时间间隔加到最早开始时间上，从而获得从最早时间到最后充值时间VIP时长
        if (updateVipExpire) {
          updateVipExpire.add(timeStep, "ms");
        } else {
          // 还没有值时，取结束时间
          updateVipExpire = moment(item.end_time);
        }
      }
    });
    const vip_expire = updateVipExpire
      ? updateVipExpire.format("YYYY-MM-DD hh:mm:ss")
      : "1970-01-01 00:00:01";

    const exchange_record = await this.service.share.exchangeList(uid);
    const exchangeIds = exchange_record.reduce(
      (total, cur, index, arr) => total.add(cur.pro_id) && total,
      new Set()
    );
    console.log("vip_expire==>", vip_expire);
    // 强制阅览器不缓存
    ctx.cacheControl = { noCache: true };
    ctx.respond({
      vip_expire,
      record,
      pay_product_ids: Array.from(payProductIdSets),
      exchange_record,
      exchange_ids: Array.from(exchangeIds),
    });
  }
};
